package com.example;

import org.objectweb.asm.*;

import java.io.FileInputStream;
import java.io.FileOutputStream;

public class ClassModifier {
    public static void main(String[] args) throws Exception {
        // 修改前后路径，注意备份原文件！
        String inputPath = "D:\\java\\lianxidemo\\demomian\\demomian\\out\\production\\demomian\\com\\example\\RRm.class";
        String outputPath = "D:\\java\\lianxidemo\\demomian\\demomian\\out\\production\\demomian\\com\\example\\RRm.class"; // 直接覆盖

        ClassReader cr = new ClassReader(new FileInputStream(inputPath));
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) {
            @Override
            public MethodVisitor visitMethod(int access, String name, String descriptor,
                                             String signature, String[] exceptions) {
                MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);

                if (name.equals("hello") && descriptor.equals("()V")) {
                    return new MethodVisitor(Opcodes.ASM9, mv) {
                        @Override
                        public void visitInsn(int opcode) {
                            // 在所有返回指令前插入打印语句
                            if (opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) {
                                // 获取 System.out
                                super.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out",
                                        "Ljava/io/PrintStream;");

                                // 构造 char[] {'H','e','l','l','o'} 动态生成字符串
                                super.visitIntInsn(Opcodes.BIPUSH, 5); // 数组长度5
                                super.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_CHAR);
                                char[] chars = {'H', 'e', 'l', 'l', 'o'};
                                for (int i = 0; i < chars.length; i++) {
                                    super.visitInsn(Opcodes.DUP);
                                    super.visitIntInsn(Opcodes.BIPUSH, i);
                                    super.visitIntInsn(Opcodes.BIPUSH, chars[i]);
                                    super.visitInsn(Opcodes.CASTORE);
                                }

                                // new String(char[])
                                super.visitTypeInsn(Opcodes.NEW, "java/lang/String");
                                super.visitInsn(Opcodes.DUP_X1);
                                super.visitInsn(Opcodes.SWAP);
                                super.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/String",
                                        "<init>", "([C)V", false);

                                // 调用 println(String)
                                super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream",
                                        "println", "(Ljava/lang/String;)V", false);
                            }
                            super.visitInsn(opcode);
                        }
                    };
                }
                return mv;
            }
        };

        cr.accept(cv, 0);
        byte[] bytes = cw.toByteArray();
        try (FileOutputStream fos = new FileOutputStream(outputPath)) {
            fos.write(bytes);
        }
    }
}
